#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)

enum
{
    OK,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERROR,
    NOTOK
};

// 增加长度报头
std::string EnLength(const std::string &text)
{
    // "x op y" -> "content_len"\r\n"x op y"\r\n
    std::string send_string = std::to_string(text.size());

    send_string += LINE_SEP;
    send_string += text;
    send_string += LINE_SEP;

    return send_string;
}
// 去掉长度报头
bool DeLength(const std::string &package, std::string *text)
{
    // "content_len"\r\n"x op y"\r\n -> "x op y"
    auto pos = package.find(LINE_SEP);
    if (pos == std::string::npos)
        return false;
    std::string text_len_string = package.substr(0, pos);
    int text_len = std::stoi(text_len_string);
    *text = package.substr(pos + LINE_SEP_LEN, text_len);

    return true;
}

/*
关于协议：
    没有规定网络通信只能由一种协议！所以，当有多种协议时，怎么让os知道我们要使用哪一种协议？
    以此为例："content_len"\r\n"协议编号"\r\n"x op y"\r\n
    通过协议编号告诉os要使用哪种协议。
*/

class Request
{
public:
    Request(int x = 0, int y = 0, char op = 0) : _x(x), _y(y), _op(op)
    {
    }
    bool serialize(std::string *out)
    {
        // 结构化->"x op y"
#ifdef MYSELF
        out->clear();
        std::string x_string(std::to_string(_x));
        std::string y_string(std::to_string(_y));

        *out += x_string;
        *out += SEP;
        *out += _op;
        *out += SEP;
        *out += y_string;
        // *out += LINE_SEP;
#else
        Json::Value root;   // Json::Value是一个万能对象类型，可以接收任何类型
        root["first"] = _x; // json重载了[]。且会自动将整数转换为字符串
        root["second"] = _y;
        root["oper"] = _op;

        // 序列化
        Json::FastWriter writer;
        // Json::StyledWriter writer;

        *out = writer.write(root);
#endif
        return true;
    }
    bool deserialize(std::string &in)
    {
        // "x op y" -> 结构化
#ifdef MYSELF
        auto left_space = in.find(SEP);
        auto right_space = in.rfind(SEP);
        if (left_space == std::string::npos || right_space == std::string::npos)
            return false;
        if (left_space == right_space)
            return false;
        if (right_space - (left_space + SEP_LEN) != 1)
            return false;

        std::string x_string = in.substr(0, left_space);
        std::string y_string = in.substr(right_space + SEP_LEN, in.size() - (right_space + SEP_LEN));
        if (x_string.empty() || y_string.empty())
            return false;

        _x = std::stoi(x_string);
        _y = std::stoi(y_string);
        _op = in[left_space + SEP_LEN];
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root); // 从in中解析放到root里

        _x = root["first"].asInt();
        _y = root["second"].asInt();
        _op = root["oper"].asInt(); // char类型本身就是整数
#endif

        return true;
    }

public:
    // 约定 "x op y"
    int _x;
    int _y;
    char _op;
};

class Response
{
public:
    Response(int exitcode = OK, int result = 0) : _exitcode(exitcode), _result(result)
    {
    }
    bool serialize(std::string *out)
    {
        // 结构化->"exitcode result"
#ifdef MYSELF
        out->clear();
        std::string ec_string = std::to_string(_exitcode);
        std::string res_string = std::to_string(_result);

        *out += ec_string;
        *out += SEP;
        *out += res_string;
#else
        Json::Value root;
        root["exitcode"] = _exitcode;
        root["result"] = _result;

        Json::FastWriter writer;
        *out = writer.write(root);
#endif
        return true;
    }
    bool deserialize(const std::string &in)
    {
        // "exitcode result" -> 结构化
#ifdef MYSELF
        auto mid_sep = in.find(SEP);
        if (mid_sep == std::string::npos)
        {
            _exitcode = NOTOK;
            return false;
        }

        std::string ec_string = in.substr(0, mid_sep);
        std::string res_string = in.substr(mid_sep + SEP_LEN, in.size() - (mid_sep + SEP_LEN));
        if (ec_string.empty() || res_string.empty())
        {
            _exitcode = NOTOK;
            return false;
        }
        _exitcode = std::stoi(ec_string);
        _result = std::stoi(res_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        _exitcode = root["exitcode"].asInt();
        _result = root["result"].asInt();
#endif
        return true;
    }

public:
    int _exitcode; // 0: 计算成功  非0: 计算失败
    int _result;
};

bool ParseOnePackage(std::string &inBuffer, std::string *text)
{
    // "content_len"\r\n"x op y"\r\n

    // static std::string inBuffer;// 多线程会出问题
    *text = "";
    // 分析
    auto pos = inBuffer.find(LINE_SEP);
    if (pos == std::string::npos)
        return false; // 报文不完整
    std::string text_len_string = inBuffer.substr(0, pos);
    int text_len = std::stoi(text_len_string);                                       // 报文有效载荷的长度
    int total_len = text_len_string.size() + LINE_SEP_LEN + text_len + LINE_SEP_LEN; // 完整报文的长度

    if (inBuffer.size() < total_len)
        return false; // 报文不完整

    // 走到这里，缓冲区中有至少一个完整的报文
    *text = inBuffer.substr(0, total_len);
    inBuffer.erase(0, total_len);

    return true;
}

// // Demo
// bool recvPackageAll(int sockfd, std::vector<std::string> *out)
// {
//     std::string inBuffer;
//     std::string singleRequest;
//     while (recvPackage(sockfd, inBuffer, &singleRequest))
//     {
//         out->push_back(singleRequest);
//     }
// }
